SVG 動畫很常在一些使用者互動上看到,例如 Navbar 上的小漢堡。而在 motion API SVG 也可以變成 motion.path
、motion.circle
... 這類元件直接進行操作。我對 SVG 還在摸索,今天主要以實現簡單的動畫為主。
在 CSS 中 SVG 線段動畫會使用到 stroke-dashoffset
、 stroke-dasharray
來控制。而在 motion 元件中要直接操作可以使用類似屬性來達效果 :
pathLength
: 以使用者單位 (user units) 指定路徑的總長度。通過使用比率 pathLength/(路徑長度的計算值) 縮放所有距離計算來校準瀏覽器與圖片本身距離計算。例如 : stroke-dasharray
的起點是 0 終點就是 pathLength
。pathSpacing
: 對應到 stroke-dasharray
的第二個數值,每個切割線段間距多少。pathOffset
: 對應到 stroke-dashoffset
線段的位移量註 : 使用者單位 (user units) 是什麼 ? 可以參考 這篇文章提到的 SVG 規範
// CSS
.checkbox{
width: 150px;
height: 150px;
border-radius: 30px;
cursor: pointer;
}
// JS
const [isChecked, setIsChecked] = useState(false);
<motion.div
className="checkbox"
animate={{
scale: isChecked ? 1 : 0.8,
backgroundColor: isChecked
? "rgba(0,0,0,1)"
: "rgba(0,0,0,.4)",
}}
transition={{ type: "spring", stiffness: 300, damping: 20 }}
onTap={() => setIsChecked(!isChecked)}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="150"
height="150">
<motion.path
d="M38 74.707l24.647 24.646L116.5 45.5"
fill="transparent"
strokeWidth="20"
stroke="#fa0"
strokeLinecap="round"
animate={{
pathLength: isChecked ? 0.9 : 0,
opacity: isChecked ? 1 : 0,
}}
/>
</svg>
</motion.div>
在操作圖形變形動畫,framer motion 官方建議搭配 flubber ,主要的目的是矯正圖形之間節點變換的問題,如果 A、B 兩張圖,依靠座標點來進行位移,從 A1 點移到 B1 點的位置可能跑到非常遙遠的位置,導致破圖,另一個就是兩張圖節點數不同,變成點憑空出現,這些問題導致圖片在轉化過程破損。
操作 SVG 我沒有很多經驗,最多使用到線段動畫而已,爬文過程中發現原來 SVG 還有更多的屬性可以操作,例如 SMIL,提供更多語意化標籤直接操作動畫。這些標籤也都可以搭配 motion 元件。
下一個章節會來認識 Motion values 的 Hooks ,這些 Hooks 可以追蹤動畫的狀態,做出更細微的互動動畫效果。